package cn.net.autocode.platform.factory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class SpringBeanFactory implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    private static BeanDefinitionRegistry beanDefinitionRegistry;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanFactory.applicationContext = applicationContext;
    }


    public static <T> T getBeanByName(Class<T> beanType, String beanName){
        if(applicationContext.containsBean(beanName)){
            return applicationContext.getBean(beanName,beanType);
        }else{
            return null;
        }
    }

    public static <T> List<T> getBeansByType(Class<T> beanType){
        String[] beanNames = applicationContext.getBeanNamesForType(beanType);
        List<T> list =  new ArrayList<>();
        for(String beanName:beanNames){
            T bean = applicationContext.getBean(beanName,beanType);
            list.add(bean);
        }
        return list;
    }

    public static Map<String,Object> getBeansByAnnotation(Class<? extends java.lang.annotation.Annotation> annotationType){
        return applicationContext.getBeansWithAnnotation(annotationType);
    }

    public static <T> T getBeanByType(Class<T> beanType){
        return applicationContext.getBean(beanType);
    }

    public static boolean beanExists(String beanName){
        return applicationContext.containsBean(beanName);
    }

    public static BeanDefinitionRegistry getBeanRegistry(){
        if(beanDefinitionRegistry==null){
            ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) SpringBeanFactory.applicationContext;
            beanDefinitionRegistry = (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory();
        }
        return beanDefinitionRegistry;
    }

    public static  void removeBean(String beanName){
        if(applicationContext.containsBean(beanName)){
            SpringBeanFactory.getBeanRegistry().removeBeanDefinition(beanName);
        }
    }

    public static  void registryBean(String beanName, BeanDefinitionBuilder beanDefinitionBuilder){
        SpringBeanFactory.getBeanRegistry().registerBeanDefinition(beanName, beanDefinitionBuilder.getRawBeanDefinition());
    }

}
